package com.train.webadmin.app.util;

import com.alibaba.fastjson.JSONObject;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

public class LongitudeAndLatitudeToAddress {

    private static final double PI = 3.1415926535897932384626;

    private static final double ee = 0.00669342162296594323;

    private static final double a = 6378245.0;

    private static final String GAO_DE_KEY = "8cc5d48bda65af2d13f06146d8b89951";

    public static String getAddressByJWD(double clog, double clat) {
        double[] doubles = LongitudeAndLatitudeToAddress.transformWGS84ToGCJ02(clog, clat);
        //lat 小  log  大
        //参数解释: 纬度,经度 采用高德API可参考高德文档https://lbs.amap.com/
        //注意key是在高德开放平台申请的key,具体获得key的步骤请查看网址:https://developer.amap.com/api/webservice/guide/create-project/get-key
        String parameters = "?key=" + GAO_DE_KEY;
        parameters += "&location=" + doubles[0] + "," + doubles[1];//经纬度坐标
        parameters += "&extensions=all";//返回结果控制，extensions 参数取值为 all 时会返回基本地址信息、附近 POI 内容、道路信息以及道路交叉口信息。
//        parameters+="&batch=false";//批量查询控制，batch 参数设置为 false 时进行单点查询，此时即使传入多个经纬度也只返回第一个经纬度的地址解析查询结果。
//        parameters+="&roadlevel=0";//道路等级，当 roadlevel = 0 时，显示所有道路
        parameters += "&output=JSON";
        parameters += "&radius=100";//搜索半径，radius取值范围在0~3000，默认是1000。单位：米
        String urlString = "https://restapi.amap.com/v3/geocode/regeo" + parameters;
        StringBuilder res = new StringBuilder();
        try {
//            log.info("高德地图请求地址："+urlString);
            URL url = new URL(urlString);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setDoOutput(true);
            conn.setRequestMethod("GET");
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
            String line;
            while ((line = in.readLine()) != null) {
                res.append(line);
            }
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        JSONObject resultSucces = JSONObject.parseObject(res.toString());
        JSONObject addr=resultSucces.getJSONObject("regeocode");
        String address = addr.get("formatted_address").toString();
        return address;
    }

    private static double transformLat(double lng, double lat) {
        double ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
        ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
        ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
        return ret;
    }
    private static double transformLng(double lng, double lat) {
        double ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
        ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
        ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
        return ret;
    }

    public static double[] transformWGS84ToGCJ02(double lng, double lat) {
        if (outOfChina(lng, lat)) {
            return new double[]{lng, lat};
        } else {
            double dLat = transformLat(lng - 105.0, lat - 35.0);
            double dLng = transformLng(lng - 105.0, lat - 35.0);
            double redLat = lat / 180.0 * PI;
            double magic = Math.sin(redLat);
            magic = 1 - ee * magic * magic;
            double sqrtMagic = Math.sqrt(magic);
            dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI);
            dLng = (dLng * 180.0) / (a / sqrtMagic * Math.cos(redLat) * PI);
            double mgLat = lat + dLat;
            double mgLng = lng + dLng;
            return new double[]{mgLng, mgLat};
        }
    }

    /**
     * 判断坐标是否不在国内
     *
     * @param lng 经度
     * @param lat 纬度
     * @return 坐标是否在国内
     */
    public static boolean outOfChina(double lng, double lat) {
        return (lng < 72.004 || lng > 137.8347) || (lat < 0.8293 || lat > 55.8271);
    }

}
